#include"../mqserver/mq_host.hpp"
#include<gtest/gtest.h>

// typedef std::unordered_map<std::string, std::string> empty_ssmap;

class HostTest : public testing::Test
{
public:
    virtual void SetUp() override
    {
        //std::cout << "小单元测试执行前的环境初始化开始" << std::endl;
        //std::cout << "-------------------------------" << std::endl;
        std::unordered_map<std::string, std::string> empty_ssmap = {{"k1", "v1"}};
        _host = std::make_shared<xiang11mq::VirtualHost>("host1", "./data/host1", "./data/host1/host1.db");
        //std::cout << "_host初始化成功" << std:: endl;

        _host->declareExchange("exchange1", xiang11mq::ExchangeType::DIRECT, true, false, empty_ssmap);
        _host->declareExchange("exchange2", xiang11mq::ExchangeType::DIRECT, true, false, empty_ssmap);
        _host->declareExchange("exchange3", xiang11mq::ExchangeType::DIRECT, true, false, empty_ssmap);
        //std::cout << "交换机声明结束" << std:: endl;

        _host->declareQueue("queue1", true, false, false, empty_ssmap);
        _host->declareQueue("queue2", true, false, false, empty_ssmap);
        _host->declareQueue("queue3", true, false, false, empty_ssmap);
        //std::cout << "队列声明结束" << std::endl;

        _host->bind("exchange1", "queue1", "news.music.pop#");
        _host->bind("exchange1", "queue2", "news.music.pop#");
        _host->bind("exchange1", "queue3", "news.music.pop#");

        _host->bind("exchange2", "queue1", "news.music.pop#");
        _host->bind("exchange2", "queue2", "news.music.pop#");
        _host->bind("exchange2", "queue3", "news.music.pop#");

        _host->bind("exchange3", "queue1", "news.music.pop#");
        _host->bind("exchange3", "queue2", "news.music.pop#");
        _host->bind("exchange3", "queue3", "news.music.pop#");
        //std::cout << "交换机—队列 绑定结束" << std:: endl;

        _host->basicPublish("queue1", nullptr, "hello world-1");
        _host->basicPublish("queue1", nullptr, "hello world-2");
        _host->basicPublish("queue1", nullptr, "hello world-3");

        _host->basicPublish("queue2", nullptr, "hello world-1");
        _host->basicPublish("queue2", nullptr, "hello world-2");
        _host->basicPublish("queue2", nullptr, "hello world-3");

        _host->basicPublish("queue3", nullptr, "hello world-1");
        _host->basicPublish("queue3", nullptr, "hello world-2");
        _host->basicPublish("queue3", nullptr, "hello world-3");
        //std::cout << "队列消息发布结束" << std:: endl;

        //std::cout << "-------------------------------" << std::endl;
        //std::cout << "小单元测试执行前的环境初始化结束" << std:: endl;
    }
    virtual void TearDown() override
    { 
        //std::cout << "小单元测试执行完毕后的环境清理开始" << std::endl;
        //std::cout << "--------------------------------" << std::endl;
        _host->clear();
        //std::cout << "--------------------------------" << std::endl;
        //std::cout << "小单元测试执行完毕后的环境清理结束" << std::endl;
    }
public:
    xiang11mq::VirtualHost::ptr _host;

};


TEST_F(HostTest, init_test)
{
    ASSERT_EQ(_host->existsExchange("exchange1"), true);
    ASSERT_EQ(_host->existsExchange("exchange2"), true);
    ASSERT_EQ(_host->existsExchange("exchange3"), true);

    ASSERT_EQ(_host->existsQueue("queue1"), true);
    ASSERT_EQ(_host->existsQueue("queue2"), true);
    ASSERT_EQ(_host->existsQueue("queue3"), true);

    ASSERT_EQ(_host->existsBinding("exchange1", "queue1"), true);
    ASSERT_EQ(_host->existsBinding("exchange1", "queue2"), true);
    ASSERT_EQ(_host->existsBinding("exchange1", "queue3"), true);

    
    ASSERT_EQ(_host->existsBinding("exchange2", "queue1"), true);
    ASSERT_EQ(_host->existsBinding("exchange2", "queue2"), true);
    ASSERT_EQ(_host->existsBinding("exchange2", "queue3"), true);

    
    ASSERT_EQ(_host->existsBinding("exchange3", "queue1"), true);
    ASSERT_EQ(_host->existsBinding("exchange3", "queue2"), true);
    ASSERT_EQ(_host->existsBinding("exchange3", "queue3"), true);

    xiang11mq::MessagePtr msg1 = _host->basicConsume("queue1");
    ASSERT_EQ(msg1->payload().body(), std::string("hello world-1"));
    xiang11mq::MessagePtr msg2 = _host->basicConsume("queue1");
    ASSERT_EQ(msg2->payload().body(), std::string("hello world-2"));
    xiang11mq::MessagePtr msg3 = _host->basicConsume("queue1");
    ASSERT_EQ(msg3->payload().body(), std::string("hello world-3"));
    xiang11mq::MessagePtr msg4 = _host->basicConsume("queue1");
    ASSERT_EQ(msg4.get(), nullptr);
}

TEST_F(HostTest, remove_exchange)
{
    _host->deleteExchange("exchange1");
    ASSERT_EQ(_host->existsBinding("exchange1", "queue1"), false);
    ASSERT_EQ(_host->existsBinding("exchange1", "queue2"), false);
    ASSERT_EQ(_host->existsBinding("exchange1", "queue3"), false);

}


TEST_F(HostTest, remove_queue)
{
    _host->deleteQueue("queue1");

    xiang11mq::MessagePtr msg1 = _host->basicConsume("queue1");
    ASSERT_EQ(msg1.get(), nullptr);

}

TEST_F(HostTest, ack_message)
{

    xiang11mq::MessagePtr msg1 = _host->basicConsume("queue1");
    ASSERT_EQ(msg1->payload().body(), std::string("hello world-1"));
    _host->basicAck(std::string("queue1"), msg1->payload().properties().id().c_str());

    xiang11mq::MessagePtr msg2 = _host->basicConsume("queue1");
    ASSERT_EQ(msg2->payload().body(), std::string("hello world-2"));
    _host->basicAck(std::string("queue1"), msg2->payload().properties().id().c_str());


    xiang11mq::MessagePtr msg3 = _host->basicConsume("queue1");
    ASSERT_EQ(msg3->payload().body(), std::string("hello world-3"));
    _host->basicAck(std::string("queue1"), msg3->payload().properties().id().c_str());
}

int main(int argc, char* argv[])
{
    testing::InitGoogleTest(&argc, argv);

    bool ret = RUN_ALL_TESTS();
    
    return 0;
}
